
/* ---------------------------------------
This sketch reads a linear encoder. It uses both interupts on the arduino.
poutputs one bargraph, voltage output on PWM pin 11, serial communications to LCD via the hardware serial. 
I used a simple r=100k and c=1 uF in a lowpass filter with a simple op-amp voltage follower and it seems to work.

trying to make this into a unit with 4 CV outputs, hence some variable names go that way.
Expanded to four output pins. uses a control register for each of the four channels of output to control what gets written where.
this will service two encoders eventually, requireing four interrupts.
------------------------------------------
to do
1) DONE offset function for expression mode switches 0 and 2
2) DONE multiple waveforms
3) DONE lights on pedalboard?
4) DONE fix BPM meter
5) subdivision switch for toe taps and MIDI  -  just midi now ****need to complete
6) DONE loops is slow and tempo light gets gummed up when pedals are moving interrupt issue?? checked for midi ticks in ISR loop for better timing accuracy
7) do something better with offset function, will work better to set offsets as needed esp. with wavetable outputs,,, 
   choppy now because they are all run once per loop  ... its seems writing to the LCD is the issue. need to do less frequently - looks promising
8) DONE fix the bargraph function to only wipe both ways and erase text after text was written to screen, could do with a variable per channel. Just
   drawing the bargraph would be much faster when nothing else is happening! could have two functions, BARGRAPH and BARGRAPH_CLEAN  

Pay attention to disabling interrupt during the SPI transfer, as the waveform generator is asynchronous to the rest of the loop, will crash!

imported BPM code in ver 7 worked out relationship between BPM data and waveform period in version 9... 
divided samples (2^16) by 15 then used shift right twice to convert BPM's to Hz for the lookup table (devide by 60), works better for LFO 
may want to add option to mult by 2 or 4 (and triplet 3) 

have BPM control waveform as a user option, or use pedal positions for freq / amplitude  / offset of waveform generator >>>> limits are 8 to about 1750 BPM

1) Four bar graphs correspond to the Vout Array

2) Implemented a state machine design using function pointers for the 4 control voltage outputs Vout1 to Vout4 that would 
assign the pedals to the output with the desired ramp, etc.

3) update the functArr, on interrupt frequency - one channel per loop to keep the ISR time shorter, cannot put midi in the ISR, too slow

4) probably want to turn off LED's after a few seconds following switch press, could depend on function

5) USER INTERFACE done, maybe preset save / restore one day... 

6)  digital pots used  because it is be easy to set the min and max voltages by stringing three pots together and varying
the middle one by pedal position or waveform from generator

       |                 |  5 volts
       |                 |
       /                 / 
       \ <---|           \
       /     /           /
       \     \           \ 
        /    /           /
        |    \__________>\
        |                 |
        |                 |  Ground

>>> use the functArr to send Vout for display purposes, and send SPI data to digital pots

7) digital pots:  #define SLAVESELECTA 53//ss for A device, #define SLAVESELECTB 48//ss for B device  

wiring to 20 pin ribbon cable 

took out right nd left encoders on ribbon cable, seemed to prone to noise

      arduino pin                     19    18     20      21     16                  11*
                       5v     GND    ENCOD LEFT    ENCOD RIGHT   LCD    N.C.   N.C.    1
       (red stripe)    1|      |      |      |      |      |      |      |      |      |
                                             ribbon connector
                        |      |      |      |      |      |      |      |      |      |
                       11     10      9      8      7      6      5      4      3      2  <-- ART switch and LED matrix cable
      arduino pin      0      1       2      3      4**    5**    6**    8*     9*     10*           
                                                 **current lim 100ohm    *connect 1 k pullup
                                                                       
switch positions on pedalboard:
1  5  13  12  8  4  0
3  7  15  14  10  6  2
Note: there is no LED for 1,3,9,11 B00001111 turns off LED's - no switch in position 9, 11


Vout array set up with Mid scale to start,  256 resolution on PWM output (256 is full scale output) , 
MIDI register is half that (original ART function) so divide  by 2
*/

#include <avr/interrupt.h>
#include <EEPROM.h>

//encoder pinouts
#define encoder0PinA  21            //Quadrature Track A encoder0
#define encoder0PinB  20            //Quadrature Track B encoder0
#define encoder1PinA  19            //Quadrature Track A encoder1
#define encoder1PinB  18            //Quadrature Track B encoder1

//#define UNKNOWN 0
//#define EXP 1
//#define LFO 2
//#define MIDI_SYNC 3

//#define R_PED 0
//#define R_PED_INV 1
//#define L_PED 2
//#define L_PED_INV 3
//#define W_OUT 4
//#define HOLD_C 5

//#define SQU 0
//#define TRI 1
//#define SIN 2
//#define SIN1 3
//#define RAMP 4
//#define SAW 5

#define PRESET_SIZE 28
#define CHAN_PRESET_SIZE 7
#define NUM_PRESETS 10
#define NUM_CHANNELS 4
#define PRESET_OFFSET 32
#define CURRENT_PRESET_ADDRESS 8

//SPI pinouts
#define DATAOUT 51//MOSI
#define DATAIN 50//MISO - not used, but part of builtin SPI
#define SPICLOCK  52//sck
#define SLAVESELECTA 53//ss for A device
#define SLAVESELECTB 48//ss for B device  

#define POT_A 14 //analog input PIN 14 for selector switch (simple voltage divider)

//setup for tap tempo functions
#define A_SW 3 //slow switch input pin
#define B_SW 2 //fast switchinput pin
#define tapLED 4  // tap tempo LED output pin 
int tapDelta = 0;
int BPM = 60;

//wavetable stuff
#define wave_led_pin 6      //waveform generator LED output pin

//midi timing function variables for midi in / out
boolean start_flag = false;    //synch the LFO, send out start message
boolean midi_clock_flag = false;  //user has selected midi clock output

#define  midi_start 0xfa
#define  midi_stop 0xfc
#define midi_clock 0xf8
#define midi_continue 0xfb
volatile byte play_flag = 0;     //used for midi clock input - valid clock input state
volatile byte data;

volatile boolean subdivide = false;
volatile boolean midi_tap = false;
volatile unsigned long midi_beat_time = 0;
volatile byte count_sync = 0;
volatile byte count_out_sync = 0;
volatile byte midi_ticks = 0;

// set up functions: add to this list as functions are developed!

void (*functArr[4])(int);        //function pointer assignable to each channel
void (*PREV_functArr[4])(int);
void LEFT_PED(void);
void LEFT_PED_INV(void);
void RIGHT_PED(void);
void RIGHT_PED_INV(void);
void HOLD_CHAN(void);
void WAVEOUT(void);
void LEFT_PED_LOWER_OFFSET(void);
void RIGHT_PED_LOWER_OFFSET(void);
void LEFT_PED_UPPER_OFFSET(void);
void RIGHT_PED_UPPER_OFFSET(void);




//user modifiers for functions: add to this list as functions are developed!
int scale[4] = {NULL};
int topval[4] = {NULL};
int bottomval[4] = {NULL};
int old_topval[4] = {255, 255, 255, 255};
int old_bottomval[4] = {0, 0, 0, 0};

boolean top_offset[4] = {false, false, false, false};  //flag to pass to main loop to ipdate offsets
boolean bottom_offset[4] = {false, false, false, false};
boolean HI_LOW_OFFSET[4] = {false, false, false, false}; //mode for waveform generator if true, left and right pedals are the boundaries for the waveform
byte function[4] = {0, 0, 2, 2};  //function array for channels used for interface default is L, L, R, R 
boolean HOLD_FLAG[4] = {false, false, false, false};
boolean keypress = false; // used to toggle switches
unsigned long last_keypress = 0; // used to debounce keypad
boolean Set_Lower = false;        // logic to set lower offsets
boolean Save_Lower[4] = {false, false, false, false};
boolean Set_Upper = false;        // logic to set upper offsets 
boolean Save_Upper[4] = {false, false, false, false};
boolean offset_lockout = false;
boolean clean[4] = {false, false, false, false};

// misc global system variables
int i = 0;           //counter
int switchin = 0;      //result of switch input read
int swnum = 1;      // switch number result
boolean light_led[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
boolean blink_led[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
boolean blink_disable = false;
boolean disp_bargraph = false;
//int currentPreset = 0;

// array "led" will sequentially light the LED's on the pedalboard
byte led[] = {B00011011, B00101011, B01001011, B01000111, B00100111, B00010111, B00011101, 
B00101101, B01001101, B01001110, B00101110, B00011110};

//array "switchled" correspponds to the swnum variable to turn on the corresponding LED to a switch activation
byte switchled[] = {B00011110, B00001111, B00011011, B00001111, B00101110, B00011101, B00101011, 
B00010111, B01001110, B00001111, B01001011, B00001111, B01001101, B00101101, B01000111, B00100111};

// array "strobe" cyles the LOW between the common 4 line matrix to read input switches
byte strobe[] = {B00001110, B00001101, B00001011, B00000111};

//define wavetable phase variables

byte *waveArr[4];  //pointer for wavetable lookup assigned to each channel
volatile unsigned int phase = 0;
volatile unsigned int phase_tab = 0;
volatile unsigned int phaseDelta = 0;
//byte Mult[4] = {8, 8, 8, 8};    // freq multiplier for wavetable to adjust for other note length values

// define the timer counter variables
unsigned int latency;
unsigned int latencySum;
unsigned int sampleCount;
unsigned char timerLoadValue;


//encoder variables
volatile int  encoder0Pos = 64;      //the encoder position variable RIGHT PEDAL
volatile int  encoder1Pos = 64;      //the encoder position variable LEFT PEDAL
volatile int  old_encoder0Pos[4] = {64, 64, 64, 64};      //the previous encoder position variable RIGHT PEDAL
volatile int  old_encoder1Pos[4] = {64, 64, 64, 64};      //the previous encoder position variable LEFT PEDAL
volatile int resistance = 0;          //lookuptable for wave gen
int potval = 0;

// variables for producing bar graph display need to change lables?
int N = 0;                           
int Num_5 = 0;
int cursor1 = 0;
int cursor2 = 0;
int cursor3 = 0;
int cursor4 = 0;
int I = 0;
boolean display_BPM = false;
byte curs[4] = {0,0,0,0};

//tap tempo stuff for loop
int lastslowState = LOW;
int lastfastState = LOW;
int slowState = LOW;
int fastState = LOW;

unsigned long currentTimer[2] = {500, 500};  /* array of most recent tap counts */
unsigned long timeoutTime = 0;  /* this is when the timer will trigger next */
unsigned long indicatorTimeout; /* for our fancy "blink" tempo indicator */

volatile boolean inhibit_LED = false; //turn off wavetable bllink while reading BPM on taps

////VoutXCR =   0 channel "off"    // the VoutCR thing needs to be reworked!
////            1 display BPM
////            2 display footpedal forward or reversed
////            3 Reversed output from Encoder 0
////            4 Output from Encoder 1
////            5 Reversed output from encoder 1
//
//byte VoutCR[4] = {2, 2, 2, 2};        //control registers to determine what device is setting voltage level *clean this up?
//                            //defaults to left encoder to 1 and 2: encoder 0
//                            //defaults to right encoder 3 and 4: encoder 1

int Vout[4] = {124, 124, 124, 124};        //Array output value for CV1 for PWM 256 resolution
int wave_channel[4] = {0, 0, 0, 0};              // this vector sets waveforms to the corresponding "1" in channel
int MIDIcc[6] = {102, 103, 104, 105, 20, 64};          //MIDI cc numbers correspond to continuous channels 1-4, last two sw 1 & sw 3
boolean MIDIVout[4] = {false, false, false, false};
boolean midi_button_1 = false;
boolean midi_button_3 = false;
byte zcount = 0;           //for switch matrix read

//Setup Timer2.
#define TIMER_CLOCK_FREQ 250000.0 //250kHz for 64 prescale from 16MHz for the timer2 interrupt had to use a slower clock to get a divide by 15 to work for BPM convert
//Configures the 8-Bit Timer2 to generate an interrupt at the specified frequency (timeout frequency)
//Returns the time load value which must be loaded into TCNT2 inside your ISR routine and will account for latency to keep this freq solid.

  unsigned char SetupTimer2(float timeoutFrequency){
  unsigned char result; //The value to load into the timer to control the timeout interval.

//  //Calculate the timer load value  ...larger the number, the sooner the interrupt fires... higher freq
  result=(int)((257.0-(TIMER_CLOCK_FREQ/timeoutFrequency))+0.5); //the 0.5 is for rounding;
  //The 257 really should be 256 but I get better results with 257, dont know why.
 TCCR2A = 0;
 TCCR2B |= (1<<CS22);    // turn on CS22 bit these two lines is  divide by 64 prescaler
 TCCR2B &= ~((1<<CS21) | (1<<CS20));    // turn off CS21 and CS20 bits
  //Timer2 Overflow Interrupt Enable   
 TIMSK2 = 1<<TOIE2;
  //load the timer for its first cycle
  TCNT2=result; 
  
 return(result);
}

